import  EventManage  from '@/core/EventWithDelegateMgr';
export default class $Element{
    private $ele:HTMLElement | HTMLCollectionOf<Element> | null = null;
    protected finder:string | HTMLElement | Element;
    private eventMgr:EventManage;
    constructor(elementTag:string | HTMLElement | Element){
        this.finder = elementTag;
        if(typeof elementTag=="string" && (new RegExp(/\.(.*?)/g)).test(elementTag)){
            this.$ele = document.getElementsByClassName(elementTag.substring(1));
        }else if(typeof elementTag=="string" &&(new RegExp(/\#(.*?)/g)).test(elementTag)){
            this.$ele = document.getElementById(elementTag.substring(1));
        }else if(typeof elementTag=="string" && (new RegExp(/\<(.*?)\/\>/g)).test(elementTag)){
            this.$ele = document.createElement(elementTag.replace("<","").replace("/>",""));
        }else if(typeof elementTag=="string"){
            this.$ele = document.getElementsByTagName(elementTag);
        }else if(elementTag instanceof HTMLElement){
            this.$ele = elementTag;
        }else{
            this.$ele = null;
        }
        this.eventMgr = new EventManage(this);
    }
    get current(){
        return this.$ele;
    }
    get children(){
        const children:$Element[] = [];
        if(this.current instanceof HTMLElement){
            for(let i=0;i<this.current.children.length;i++){
                children.push(new $Element(this.current.children[i]))
            }
        }else if(this.current instanceof HTMLCollection){
            for(let i=0;i<this.current.length;i++){
                for(let j=0;j<this.current[i].children.length;j++){
                    children.push(new $Element(this.current[i].children[j]))
                }
            }
        }
        return children;
    }
    /**
     * 传入进来的元素是否是自己的同类
     */
    is(ele:HTMLElement | Element){
        if(this.current instanceof HTMLElement){
            return this.current === ele;
        }else if(this.current instanceof HTMLCollection){
            let is = false;
            for(let i=0;i<this.current.length;i++){
                if(this.current[i] === ele){
                    is = true;
                    break;
                }
            }
            return is;
        }
    }
    getChild(elementTag:string | HTMLElement | Element){
        return new $Element(elementTag);
    }
    empty(){
        for(let i=0;i<this.children.length;i++){
            this.emptyDom(this.children[i]);
        }
        this.emptyTextContent();
    }
    private emptyTextContent(){
        if(this.current instanceof HTMLElement){
            this.current.textContent = "";
        }else if(this.current instanceof HTMLCollection){
            for(let i=0;i<this.current.length;i++){
                this.current[i].textContent = "";
            }
        }
    }
    private emptyDom(ele:$Element){
        const elChildrens = ele.children;
        for(let i=0; i < elChildrens.length; i++){
            this.eventMgr.removeDOMEventListener(ele)
        }
    }
    private setDOMStyle(ele:HTMLElement|Element,styleCode:string,propName?:string){
        if(propName){
            (<any>ele).style[propName] = styleCode;
        }else{
            ele.setAttribute("style",styleCode);
        }
    }
    private addDOMClassName(ele:HTMLElement|Element,className:string){
        ele.setAttribute("class", (ele.getAttribute("class")||"")+" "+className);

    }

    private removeDOMClassName(ele:HTMLElement|Element,className:string){
        ele.setAttribute("class", ele.getAttribute("class")?.replace(" "+className,"") || "");
    }

    private removeDOMChild(ele:HTMLElement|Element,child:$Element){
        if(child.current instanceof HTMLElement){
            ele.removeChild(child.current);
        }else if(child.current instanceof HTMLCollection){
            for(let i=0;i<child.current.length;i++){
                ele.removeChild(child.current[i]);
            }
        }
    }
    private addDOMChild(ele:HTMLElement|Element,child:$Element){
        if(child.current instanceof HTMLElement){
            ele.appendChild(child.current);
        }else if(child.current instanceof HTMLCollection){
            for(let i=0;i<child.current.length;i++){
                ele.appendChild(child.current[i]);
            }
        }
    }
    appendChild(element: $Element){
        if(this.current instanceof HTMLElement){
            this.addDOMChild(this.current,element);
        }else if(this.current instanceof HTMLCollection){
            for(let i=0;i<this.current.length;i++){
                const ele = this.current[i];
                this.addDOMChild(ele,element);
            }
        }
    }
    removeChild(element: $Element){
        if(this.current instanceof HTMLElement){
            this.removeDOMChild(this.current,element);
        }else if(this.current instanceof HTMLCollection){
            for(let i=0;i<this.current.length;i++){
                const ele = this.current[i];
                this.removeDOMChild(ele,element);
            }
        }
    }

    setStyle(styleCode:string){
        if(this.current instanceof HTMLElement){
            this.setDOMStyle(this.current,styleCode)
        }else if(this.current instanceof HTMLCollection){
            for(let i=0;i<this.current.length;i++){
                const ele = this.current[i];
                this.setDOMStyle(ele,styleCode)
            }
        }
    }
    setStyleWithProp(propName:string,styleCode:string){
        if(this.current instanceof HTMLElement){
            // (<any>this.current.style)[propName] = styleCode;
            this.setDOMStyle(this.current,styleCode,propName)
        }else if(this.current instanceof HTMLCollection){
            for(let i=0;i<this.current.length;i++){
                const ele = this.current[i];
                this.setDOMStyle(ele,styleCode,propName)
            }
        }
    }
    addClassName(className:string){
        if(this.current instanceof HTMLElement){
            this.addDOMClassName(this.current,className);
            // (<HTMLElement>this.current).setAttribute("class", (<HTMLElement>this.current).getAttribute("class")+" "+className);
        }else if(this.current instanceof HTMLCollection){
            for(let i=0;i<this.current.length;i++){
                const ele = this.current[i];
                this.addDOMClassName(ele,className);
                // ele.setAttribute("class",ele.getAttribute("class")+" "+className);
            }
        }
    }
    removeClassName(className:string){
        if(this.current instanceof HTMLElement){
            this.removeDOMClassName(this.current,className);
        }else if(this.current instanceof HTMLCollection){
            for(let i=0;i<this.current.length;i++){
                const ele = this.current[i];
                this.removeDOMClassName(ele,className);
            }
        }
    }
    addEventDelegate(eventName:string, fn:(event:Event)=>boolean|undefined|void, target?:$Element){

    }
    addEventListener(eventName:string, fn:(event:Event)=>boolean|undefined|void){
        this.eventMgr.addEventListener(eventName,fn);
    }
    removeEventListener(eventName:string|string[]){
        if(eventName instanceof Array){
            eventName.forEach(evtName=>{
                this.eventMgr.removeEventListener(evtName);
            })
        }else{
            this.eventMgr.removeEventListener(eventName);
        }
        
    }

    removeEventDelegate(eventName:string|string[], target?:$Element){
        if(eventName instanceof Array){
            eventName.forEach(evtName=>{
                this.eventMgr.removeEventListener(evtName);
            })
        }else{
            this.eventMgr.removeEventListener(eventName);
        }
    }
}